package cn.melonlib.tools.db.schemas.comp.dao.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.melonlib.cores.jpa.comp.Dao;
import cn.melonlib.tools.db.schemas.comp.dao.ModelDescriptionRetrieval;
import cn.melonlib.tools.db.schemas.model.views.ModelDescription;
import cn.melonlib.tools.db.schemas.model.views.ModelField;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.intellij.lang.annotations.Language;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import javax.persistence.Query;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Repository()
//@ConditionalOnProperty(value = {"db.type"},prefix = "cn.melonlib.tools",havingValue = "mysql",matchIfMissing = true)
public class MysqlDatabaseSchemasDao implements ModelDescriptionRetrieval {

    @Resource
    private Dao dao;

    @Override
    public List<ModelDescription> getModels(String schemaName,Map<String,String> params) {
        return dao.query(entityManager -> {
            @Language("HQL") String tableQuery="select TABLE_NAME , TABLE_COMMENT ,TABLE_ROWS ,TABLE_SCHEMA ,TABLE_TYPE  from information_schema.TABLES t where TABLE_SCHEMA = ?1";
            @Language("HQL") String columnQuery="select COLUMN_NAME ,COLUMN_COMMENT ,TABLE_SCHEMA ,COLUMN_TYPE ,TABLE_NAME ,CHARACTER_MAXIMUM_LENGTH ,NUMERIC_PRECISION ,ORDINAL_POSITION ,COLUMN_KEY,COLUMN_DEFAULT,IS_NULLABLE  from information_schema.`COLUMNS` c where TABLE_SCHEMA =?1 ";
            Query cquery= entityManager.createNativeQuery(columnQuery);
            cquery.setParameter(1,schemaName);
            Map<String,List<ModelField>> columnsMap= (Map<String,List<ModelField>>)cquery.getResultList().stream().map(row->{
                Object[] data=(Object[]) row;
                ModelField dc=new ModelField();
                dc.setName(data[0].toString());
                dc.setComment(ObjectUtils.defaultIfNull(data[1],"").toString());
                dc.setSchemas(data[2].toString());
                dc.setColumnType(data[3].toString());
                dc.setTableName(data[4].toString());
                dc.setColumnLength(ObjectUtils.<Number>defaultIfNull((Number) data[5],ObjectUtils.<Number>defaultIfNull((Number) data[6],0)).longValue());
                dc.setOrdinal(((Number)data[7]).intValue());
                dc.setPrimaryKey(StringUtils.isNotBlank((String)data[8]));
                dc.setDefaultValue(Objects.equals(ObjectUtils.defaultIfNull(data[9],"NULL"),"NULL")?"<空值>":data[9].toString());
                dc.setNullAble(Objects.equals(data[10],"YES"));
                return dc;
            }).collect(Collectors.groupingBy(dc-> BeanUtil.getProperty(dc,"tableName")));
            Query tquery=entityManager.createNativeQuery(tableQuery);
            tquery.setParameter(1,schemaName);
            List<ModelDescription> tables=tquery.getResultList().stream().map(row->{
                Object[] data=(Object[]) row;
                ModelDescription dt=new ModelDescription();
                dt.setName(data[0].toString());
                dt.setComment(StringUtils.defaultIfBlank(ObjectUtils.defaultIfNull(data[1],"").toString(),"缺失表名称"));
                dt.setRows(ObjectUtils.<Number>defaultIfNull((Number) data[2],0).longValue());
                dt.setSchemas(data[3].toString());
                dt.setType(data[4].toString());
                dt.setColumns(columnsMap.get(dt.getName()));
                return dt;
            }).toList();
            return tables;
        }).getResult();
    }

    public static List<ModelDescription> getTables() throws Exception{
        ClassPathResource classPathResource=new ClassPathResource("db_schema.json");
        try(BufferedReader reader= new BufferedReader(new InputStreamReader( classPathResource.getInputStream(),"utf-8")) ){
            List<ModelDescription> tables=new ObjectMapper().readValue(reader.readLine(), new TypeReference<List<ModelDescription>>() {
            });
            return tables;
        }
    }
}
